use crate::core::Args;
use include_dir::{include_dir, Dir};
use serde_json::json;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use wang_utils::fs::create_parent_folder;

static TEMPLATE_DIR: Dir<'_> = include_dir!("src/templates");
pub fn generate(args: Args) -> anyhow::Result<()> {
    let folder_name = &args.name;
    let dir = env::current_dir()?;
    let output_folder = dir.join(folder_name);
    generate_folder(&TEMPLATE_DIR, &args, &output_folder)?;
    Ok(())
}
fn generate_folder(dir: &Dir, args: &Args, output_folder: &PathBuf) -> anyhow::Result<()> {
    for entry in dir.entries() {
        if let Some(dir) = entry.as_dir() {
            //是文件夹
            generate_folder(dir, args, output_folder)?;
        } else {
            //是文件
            let file_path = entry.path();
            let output_path = output_folder.join(file_path);
            //检查父目录是否存在，不存在则创建
            create_parent_folder(&output_path)?;
            let mut file = File::create(&output_path)?;
            if let Some(content) = entry.as_file().unwrap().contents_utf8() {
                match resolve_template(content, args) {
                    Ok(content) => {
                        println!("生成文件:{}", output_path.display());
                        file.write_all(content.as_bytes())?;
                    }
                    Err(e) => {
                        let err_msg = e.to_string();
                        let msg = format!("模板解析失败, path:{output_path:?}, msg:{err_msg}");
                        return Err(anyhow::anyhow!("{}", msg));
                    }
                }
            } else {
                file.write_all(entry.as_file().unwrap().contents())?;
            }
        }
    }
    Ok(())
}

fn resolve_template(content: &str, args: &Args) -> anyhow::Result<String> {
    let mut engine = upon::Engine::new();
    engine.add_template("source", content)?;
    // engine.add_filter("date_filter", upon_date_filter);
    // engine.add_filter("message_filter", upon_message_filter);
    let template_value = json!(args); // 将template转换为serde_json::Value
    let content = engine
        .template("source")
        .render(upon::value! {args: &template_value})
        .to_string()?;
    Ok(content)
}
